﻿using System;
using System.Configuration;
using System.Transactions;
using StockholmsStad.Data.Interfaces;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Utilities.Exceptions;
using StockholmsStad.Utilities.Enums;
using System.Data.SqlClient;
using StockholmsStad.Utilities;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;

namespace StockholmsStad.Data.Context
{
    internal class DataContext : IDataContext
    {
        private readonly TransactionScope _transactionScope;
        private readonly bool completeTransaction;

        public DataContext(bool useTransaction, bool completeTransaction, UserRole userRole)
        {
            this.completeTransaction = completeTransaction;

            if (useTransaction)
                _transactionScope = new TransactionScope();

            try
            {
                var connectionsString = userRole == UserRole.ReadOnly ? 
                    SettingsUtility.GetConnectionString("ParvisGuestConnectionString") : 
                    SettingsUtility.GetConnectionString("ParvisConnectionString");

                if (!string.IsNullOrEmpty(connectionsString))
                    StockholmsStadDataContext = new StockholmsStadDataContext(connectionsString);
                else
                    throw new StockholmStadApplicationException(ApplicationErrorCode.ConnectionStringMissing, Severity.High);
            }
            catch(SqlException e)
            {
                throw new StockholmStadApplicationException(ApplicationErrorCode.DataConnectionFailure, Severity.High, e.Message, e);
            }
            catch (Exception e)
            {
                throw new StockholmStadApplicationException(ApplicationErrorCode.UnknownError, Severity.High, e.Message, e);
            }
        }

        ///<summary>
        /// Om contextet innehåller en transaktion så rullas databasoperationenerna tillbaka.
        /// InvalidOperationException kastas om contextet inte innehåller någon transaktion
        ///</summary>
        public void TransactionDispose()
        {
            if (_transactionScope == null)
                throw new InvalidOperationException("Context does not have an internal transaction");
            _transactionScope.Dispose();
        }

        /// <summary>
        /// Om contextet innehåller en transation så köras commit på transaktionen.
        /// InvalidOperationException kastas om contextet inte innehåller någon transaktion
        /// </summary>
        public void TransactionComplete()
        {
            if (_transactionScope == null)
                throw new InvalidOperationException("Context does not have an internal transaction");
            _transactionScope.Complete();
        }

        internal StockholmsStadDataContext StockholmsStadDataContext { get; private set; }

        #region IParVisContext Members

        public void Dispose()
        {
            if (_transactionScope != null)
            {
                _transactionScope.Dispose();
            }
            StockholmsStadDataContext.Dispose();
        }

        #endregion
    }
}